﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Mesuro.Equation {
	public class EqListTerm : EqTerm, IEnumerable<EqTerm> {

		static EqListTerm() {
			LibListFunctions.Load();
		}

		public static EqListTerm Cast( EqTerm term ) {
			if (term is EqListTerm) return (EqListTerm)term;
			return new EqListTerm( term );
		}
		public static EqListTerm Combine( EqTerm term1, EqTerm term2 ) {
			EqListTerm ret = Cast( term1 );
			ret.AddRange( Cast( term2 ) );
			return ret;
		}

		private List<EqTerm> list = new List<EqTerm>();

		public int Count { get { return list.Count; } }

		public EqTerm this[int i] {
			get { return list[i]; }
			set { list[i] = value; }
		}

		public EqListTerm( params EqTerm[] terms ) {
			foreach (EqTerm t in terms)
				Add( t );
		}

		public void Add( EqTerm term ) {
			list.Add( term );
		}
		public void AddRange( EqListTerm term ) {
			list.AddRange( term.list );
		}

		public override EqTerm Evaluate( EqScope scope ) {
			return EvaluateEach( scope );
		}
		public EqListTerm EvaluateEach( EqScope scope ) {
			EqListTerm list = new EqListTerm();
			for (int i = 0; i < Count; i++)
				list.Add( this[i].Evaluate( scope ) );
			return list;
		}

		public override int ComplexityCost() {
			int cost = 0;
			foreach (EqTerm t in this)
				cost = Math.Max( cost, t.ComplexityCost() );
			return cost;
		}
		public IEnumerator<EqTerm> GetEnumerator() {
			return list.GetEnumerator();
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
			return list.GetEnumerator();
		}

		public override string ToString() {
			StringBuilder sb = new StringBuilder( "{" );
			if (list.Count > 0) {
				foreach (EqTerm t in list)
					sb.Append( t.ToString() ).Append( ", " );
				sb.Remove( sb.Length - 2, 2 );
			}
			sb.Append( "}" );
			return sb.ToString();
		}
	}
	public static class LibListFunctions {

		public static void Load() {
			EqScope.Intrinsic.CreateSymbol( "ForEach", ForEachEval, EqSymbolFlags.WriteProtect | EqSymbolFlags.Permanent | EqSymbolFlags.HoldAll, new EqListTerm( new EqSymbolInstance( "x" ), new EqSymbolInstance( "expr" ) ) );
		}

		private static EqTerm ForEachEval( EqTerm[] args ) {
			args[0].ComplexityCost();
			return args[0];
		}
	}
}
